using System;
using FireStarter.Base;
using Firestarter.Test.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.Base.Exceptions;
using Habanero.BO;
using System.Collections.Generic;
using Habanero.BO.ClassDefinition;
using Habanero.DB;
using Habanero.Test.Structure;
using NUnit.Framework;

namespace FireStarterModeller.Test.BO
{
    /// <summary>
    /// Provides a place to write custom tests for DMSolution objects.
    /// This file is only written once and can be changed.  The Def file
    /// attached to this as a dependent is rewritten with each regeneration
    /// and contains the standard tests for DMSolution.
    /// Regenerate this test project whenever there have been changes to the
    /// business objects.
    /// If tests are failing due to a unique setup in your application,
    /// you can either override the Create methods in TestUtils, or you
    /// can add the test to the ignore list below and reimplement it here.
    /// </summary>
    public partial class TestDMSolution
    {

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            //------------------------------------------------------------
            // Use this list to ignore generated tests that are failing
            // due to a unique condition in your application.
            // Remember to reimplement the test here.
            //------------------------------------------------------------
            _ignoreList.Add("Test_SingleRelationshipDeletion_DoNothing_DefaultAssembly", "cannot delete since cannot delete System Prop Types");
            _ignoreList.Add("Test_DeleteDMSolution", "cannot delete since cannot delete System Prop Types");
            _ignoreList.Add("Test_MultipleRelationshipDeletion_DeleteRelated_Assemblies", "cannot delete since cannot delete System Prop Types");
            _ignoreList.Add("Test_MultipleRelationshipDeletion_DeleteRelated_UIControlMapperTypes", "cannot delete since cannot delete System Prop Types");
            _ignoreList.Add("Test_MultipleRelationshipDeletion_DeleteRelated_UIControlTypes", "cannot delete since cannot delete System Prop Types");
            _ignoreList.Add("Test_MultipleRelationshipDeletion_DeleteRelated_UIGridColumnControlTypes", "cannot delete since cannot delete System Prop Types");
                        //Runs every time that any testmethod is executed
            TestUtilsDomain.SetupFixture();
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }

        [TearDown]
        public override void TearDownTest()
        {
            //runs every time any testmethod is complete
            base.TearDownTest();
        }

        [Test]
        public void Test_ToString()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsDMSolution.CreateUnsavedValidDMSolution();
            //---------------Assert Precondition----------------
            Assert.IsFalse(String.IsNullOrEmpty(dmSolution.SolutionName), "SolutionName Should not be null");
            //---------------Execute Test ----------------------
            string actualToString = dmSolution.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(dmSolution.SolutionName, actualToString);
        }
        [Test]
        public void Test_ToString_SolutionNameNull()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsDMSolution.CreateUnsavedValidDMSolution();
            dmSolution.SolutionName = null;
            //---------------Assert Precondition----------------
            Assert.IsTrue(String.IsNullOrEmpty(dmSolution.SolutionName), "SolutionName Should be null");
            //---------------Execute Test ----------------------
            string actualToString = dmSolution.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(dmSolution.SolutionID.ToString(), actualToString);
        }
        [Test]
        public void Test_ToString_SolutionNameNull_SolutionIDNull()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = new DMSolution();
            TestUtilsDMSolution.UpdateWithValidData(dmSolution);
            dmSolution.SolutionName = null;
            dmSolution.SolutionID = null;
            //---------------Assert Precondition----------------
            Assert.IsTrue(String.IsNullOrEmpty(dmSolution.SolutionName), "SolutionName Should be null");
            Assert.IsNull(dmSolution.SolutionID);
            //---------------Execute Test ----------------------
            string actualToString = dmSolution.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual("-unnamed solution-", actualToString);
        }

       [Test]
        public void Test_SolutionNameBoProp_IsEditable_ShouldBeTrue_WhenNotGenerated()
        {
            //--------------- Set up test pack ------------------
            DMSolution dmSolution = new DMSolution();
            //--------------- Test Preconditions ----------------
            Assert.IsFalse(dmSolution.Generated.GetValueOrDefault());
            //--------------- Execute Test ----------------------
            IBOProp prop = dmSolution.Props["SolutionName"];
            //--------------- Test Result -----------------------
            string message = "";
            Assert.AreEqual("", message);
            Assert.IsTrue(prop.IsEditable(out message));
        }

        [Test]
        public void Test_SolutionNameBoProp_IsEditable_ShouldBeFalse_WhenGenerated()
        {
            //--------------- Set up test pack ------------------
            DMSolution dmSolution = new DMSolution();
            dmSolution.Generated = true;
            //--------------- Test Preconditions ----------------
            Assert.IsTrue(dmSolution.Generated.Value);
            //--------------- Execute Test ----------------------
            IBOProp prop = dmSolution.Props["SolutionName"];
            //--------------- Test Result -----------------------
            string message;
            Assert.IsFalse(prop.IsEditable(out message));
        }

        [Test]
        public void Test_InsertNewProjectInfo()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = new DMSolution();
            TestUtilsDMSolution.UpdateWithValidData(dmSolution);

            //---------------Assert Precondition----------------
            Assert.IsTrue(dmSolution.Status.IsNew);

            //---------------Execute Test ----------------------
            dmSolution.Save();

            //---------------Test Result -----------------------
            Assert.IsFalse(dmSolution.Status.IsNew);
        }

        [Test]
        public void Test_InsertNewProjectInfo_Invalid()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = new DMSolution();

            //---------------Assert Precondition----------------
            Assert.IsTrue(dmSolution.Status.IsNew);

            //---------------Execute Test ----------------------
            try
            {
                dmSolution.Save();
                Assert.Fail("expected Err");
            }
                //---------------Test Result -----------------------
            catch (BusObjectInAnInvalidStateException ex)
            {
                StringAssert.Contains("Solution Name' is a compulsory field and has no value", ex.Message);
                //StringAssert.Contains("Solution Directory' is a compulsory field and has no value", ex.Message);
            }
            Assert.IsTrue(dmSolution.Status.IsNew);
        }

        [Ignore("The Solution can no longer be deleted since it has SystemPropTypes")] //TODO Brett 09 Feb 2010: Ignored Test - The Solution can no longer be deleted since it has SystemPropTypes
        [Test]
        public void Test_DeleteProjectInfo()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();

            //---------------Assert Precondition----------------
            Assert.IsFalse(dmSolution.Status.IsNew);
            string message;
            Assert.IsTrue(dmSolution.IsDeletable(out message));

            //---------------Execute Test ----------------------
            dmSolution.MarkForDelete();
            dmSolution.Save();

            //---------------Test Result -----------------------  
            Assert.IsTrue(dmSolution.Status.IsNew);
            Assert.IsTrue(dmSolution.Status.IsDeleted);
        }

        [Test]
        public void Test_UpdateProjectInfo()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();

            //---------------Assert Precondition----------------
            Assert.IsFalse(dmSolution.Status.IsNew);
            string message;
            Assert.IsTrue(dmSolution.IsEditable(out message));

            //---------------Execute Test ----------------------
            dmSolution.BaseProjectName = TestUtilsShared.GetRandomString();
            dmSolution.SolutionName = TestUtilsShared.GetRandomString();
            dmSolution.HabaneroDllPath = TestUtilsShared.GetRandomString();
            dmSolution.TableNamePrefix = TestUtilsShared.GetRandomString();
            dmSolution.TableNameSuffix = TestUtilsShared.GetRandomString();
            dmSolution.PascalCase = false;
            dmSolution.SolutionDirectory = TestUtilsShared.GetRandomString();
            dmSolution.UIProjectName = TestUtilsShared.GetRandomString();
            dmSolution.UITestProjectName = TestUtilsShared.GetRandomString();
            dmSolution.BOProjectName = TestUtilsShared.GetRandomString();
            dmSolution.BOTestProjectName = TestUtilsShared.GetRandomString();
            dmSolution.LogicProjectName = TestUtilsShared.GetRandomString();
            dmSolution.Generated = true;

            dmSolution.Save();

            //---------------Test Result -----------------------
            Assert.IsFalse(dmSolution.Status.IsNew);
        }

        [Test]
        public void Test_LoadProjectInfo()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            BusinessObjectManager.Instance.ClearLoadedObjects();

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            DMSolution loadedDMSolution = Broker.GetBusinessObject<DMSolution>(dmSolution.ID);

            //---------------Test Result -----------------------  
            Assert.IsFalse(loadedDMSolution.Status.IsNew);
            Assert.AreEqual(loadedDMSolution.ID, dmSolution.ID);
            //TODO: When not using memory db Assert.AreNotSame(loadedDMSolution, dmSolution);
        }

        [Test]
        public void Test_AllClasses()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            DMAssembly assembly = new DMAssembly("assembly2");
            dmSolution.Assemblies.Add(assembly);
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            assembly.Classes.CreateBusinessObject();

            //---------------Execute Test ----------------------
            BusinessObjectCollection<DMClass> allClasses = dmSolution.AllClasses;
           
            //---------------Test Result -----------------------
            Assert.AreEqual(3, allClasses.Count);
        }  
        
        [Test]
        public void Test_AllClasses_ShouldBeSortedByClassNameBO()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            DMAssembly assembly = new DMAssembly("assembly2");
            dmSolution.Assemblies.Add(assembly);
            DMClass dmClass3 = TestUtilsDMClass.CreateUnsavedDefaultDMClass(dmSolution, "zzbbbbbfdsafasdbfsdafas");
            DMClass dmClass1 = TestUtilsDMClass.CreateUnsavedDefaultDMClass(dmSolution, "aaaaafdf");
            DMClass dmClass2 = TestUtilsDMClass.CreateUnsavedDefaultDMClass(assembly, "bbbbbbbbbbbb");

            //---------------Execute Test ----------------------
            BusinessObjectCollection<DMClass> allClasses = dmSolution.AllClasses;
           
            //---------------Test Result -----------------------
            Assert.AreEqual(3, allClasses.Count);
            Assert.AreSame(dmClass1, allClasses[0]);
            Assert.AreSame(dmClass2, allClasses[1]);
            Assert.AreSame(dmClass3, allClasses[2]);
        }
        [Test]
        public void Test_CallAllClasses_Twice_ReturnsSameReference()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            DMAssembly assembly = new DMAssembly("assembly2");
            dmSolution.Assemblies.Add(assembly);
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            assembly.Classes.CreateBusinessObject();

            //---------------Execute Test ----------------------
            BusinessObjectCollection<DMClass> allClasses = dmSolution.AllClasses;
            BusinessObjectCollection<DMClass> secondAllClasses = dmSolution.AllClasses;
           
            //---------------Test Result -----------------------
            Assert.AreSame(allClasses, secondAllClasses);
            Assert.AreEqual(3, secondAllClasses.Count);
        }
        [Test]
        public void Test_AllClasses_WhenAddClassToAssembly_ShouldAddToAllClasses()
        {
            //---------------Set up test pack-------------------
            BusinessObjectCollection<DMClass> allClasses;
            DMSolution dmSolution = GetDmSolutionWith3Classes(out allClasses);
            //---------------Assert Precondition -----------------------
            Assert.AreEqual(3, allClasses.Count);
            //---------------Execute Test ----------------------
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            //---------------Test Result -----------------------
            Assert.AreEqual(4, allClasses.Count);
        }

        private DMSolution GetDmSolutionWith3Classes(out BusinessObjectCollection<DMClass> allClasses)
        {
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            DMAssembly assembly = new DMAssembly("assembly2");
            dmSolution.Assemblies.Add(assembly);
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            assembly.Classes.CreateBusinessObject();
            allClasses = dmSolution.AllClasses;
            return dmSolution;
        }

        [Test]
        public void Test_AllClasses_WhenRemoveClassToAssembly_ShouldRemoveFromAllClasses()
        {
            //---------------Set up test pack-------------------
            BusinessObjectCollection<DMClass> allClasses;
            DMSolution dmSolution = GetDmSolutionWith3Classes(out allClasses);
            DMClass dmClassToRemove = dmSolution.DefaultAssembly.Classes[1];
            //---------------Assert Precondition -----------------------
            Assert.AreEqual(3, allClasses.Count);
            Assert.AreEqual(2,dmSolution.DefaultAssembly.Classes.Count);
            //---------------Execute Test ----------------------
            dmSolution.DefaultAssembly.Classes.Remove(dmClassToRemove);
            //---------------Test Result -----------------------
            Assert.AreEqual(2, allClasses.Count);
        }

        [Test]
        public void Test_AllClasses_WhenAddClassToNewAssembly_ShouldAddToAllClasses()
        {
            //---------------Set up test pack-------------------
            BusinessObjectCollection<DMClass> allClasses;
            DMSolution dmSolution = GetDmSolutionWith3Classes(out allClasses);
            //---------------Assert Precondition -----------------------
            Assert.AreEqual(3, allClasses.Count);
            //---------------Execute Test ----------------------
            DMAssembly newAssembly = dmSolution.CreateAssembly(TestUtilsShared.GetRandomString());
            DMClass newClass = newAssembly.Classes.CreateBusinessObject();
            //---------------Test Result -----------------------
            Assert.AreEqual(4, allClasses.Count);
            Assert.Contains(newClass, allClasses);
        }

        [Test]
        public void Test_AllClasses_WhenRemoveClassFromNewAssembly_ShouldRemoveFromAllClasses()
        {
            //---------------Set up test pack-------------------
            BusinessObjectCollection<DMClass> allClasses;
            DMSolution dmSolution = GetDmSolutionWith3Classes(out allClasses);
            DMAssembly newAssembly = dmSolution.CreateAssembly(TestUtilsShared.GetRandomString());
            DMClass newClass = newAssembly.Classes.CreateBusinessObject();
            //---------------Assert Precondition -----------------------
            Assert.AreEqual(4, allClasses.Count);
            Assert.Contains(newClass, allClasses);
            //---------------Execute Test ----------------------s
            newAssembly.Classes.Remove(newClass);
            //---------------Test Result -----------------------
            Assert.AreEqual(3, allClasses.Count);
            Assert.IsFalse(allClasses.Contains(newClass));
        }
        [Test]
        public void Test_AllClasses_WhenUpdateClassProperties_ShouldRaiseEvent()
        {
            //---------------Set up test pack-------------------
            BusinessObjectCollection<DMClass> allClasses;
            DMSolution dmSolution = GetDmSolutionWith3Classes(out allClasses);
            DMAssembly newAssembly = dmSolution.CreateAssembly(TestUtilsShared.GetRandomString());
            DMClass newClass = newAssembly.Classes.CreateBusinessObject();
            bool propUpdatedEventFired = false;
            dmSolution.AllClasses.BusinessObjectPropertyUpdated += delegate {
                                                                       propUpdatedEventFired = true;
                                                                   };
            //---------------Assert Precondition -----------------------
            Assert.AreEqual(4, allClasses.Count);
            Assert.Contains(newClass, allClasses);
            Assert.IsFalse(propUpdatedEventFired);
            //---------------Execute Test ----------------------s
            newClass.ClassNameBO = TestUtilsShared.GetRandomString();
            //---------------Test Result -----------------------
            Assert.IsTrue(propUpdatedEventFired);
 
        }

        [Test]
        public void Test_AllClasses_WhenRemoveAssembly_ShouldRemoveFromallClasses()
        {
            //You cannot move an assembly to another solution and you cannnot delete an assembly if it
            //has any classes so testing and adding capability to handle removing an assembly is fruitless at present
        }

        [Test]
        public void Test_CreateAssembly()
        {
            //---------------Set up test pack-------------------
            DMSolution solution = TestUtilsShared.CreateSavedDMSolution();
            const string assemblyName = "assembly2";

            //---------------Execute Test ----------------------
            DMAssembly assembly = solution.CreateAssembly(assemblyName);
 
            //---------------Test Result -----------------------
            Assert.AreEqual(assemblyName, assembly.Name);
            //---------------Tear Down -------------------------          
        }
        [Test]
        public void Test_FindClassByMappedTableName_WithZeroClasses()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            const string mappedtablename = "MappedTableName";

            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dmSolution.AllClasses.Count);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            //---------------Execute Test ----------------------
            DMClass foundClass = dmSolution.FindClassByMappedTableName(mappedtablename);
            //---------------Test Result -----------------------
            Assert.IsNull(foundClass);
        }
        [Test]
        public void Test_FindClassByMappedTableName()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            DMClass dmClass = dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            const string mappedtablename = "MappedTableName";
            dmClass.MappedTableName = mappedtablename;
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmSolution.AllClasses.Count);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            //---------------Execute Test ----------------------
            DMClass foundClass = dmSolution.FindClassByMappedTableName(mappedtablename);
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundClass);
            Assert.AreSame(dmClass, foundClass);
        }
        [Test]
        public void Test_FindClassByMappedTableName_WithTwoClasses()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            DMClass dmClass = dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            const string mappedtablename = "MappedTableName";
            dmClass.MappedTableName = mappedtablename;
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, dmSolution.AllClasses.Count);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            //---------------Execute Test ----------------------
            DMClass foundClass = dmSolution.FindClassByMappedTableName(mappedtablename);
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundClass);
            Assert.AreSame(dmClass, foundClass);
        }
        [Test]
        public void Test_FindClassByMappedTableName_WithTwoClasses_FoundClassSecond()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            DMClass dmClass = dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            dmClass.ClassNameBO = "FoundBO";
            const string mappedtablename = "MappedTableName";
            dmClass.MappedTableName = mappedtablename;
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, dmSolution.AllClasses.Count);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.IsTrue(dmSolution.AllClasses.Contains(dmClass));
            //---------------Execute Test ----------------------
            DMClass foundClass = dmSolution.FindClassByMappedTableName(mappedtablename);
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundClass);
            Assert.AreSame(dmClass, foundClass);
        }

        //TODO Brett 16 Feb 2009: different string case
        //TODO Brett 16 Feb 2009: The precondition is that the table name is trimmed of lead and 
        // trailing white spaces.
        //TODO Brett 16 Feb 2009: It is assumed that the Mapped table name in the DMClass will be 
        //  a 100% match for the tableName in the Database i.e. if the table name is contact_person
        //  then the mappedTableName will need to be contact person else the DMClass will not be found.
        [Test]
        public void Test_FindClassByMappedTableName_WithTwoClasses_NoFoundClass()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            DMClass dmClass = dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            dmClass.ClassNameBO = "FoundBO";
            const string mappedtablename = "MappedTableName";
            dmClass.MappedTableName = "Not the MappedTable";
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, dmSolution.AllClasses.Count);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.IsTrue(dmSolution.AllClasses.Contains(dmClass));
//            Assert.AreSame(dmClass, dmSolution.AllClasses[1]);
            //---------------Execute Test ----------------------
            DMClass foundClass = dmSolution.FindClassByMappedTableName(mappedtablename);
            //---------------Test Result -----------------------
            Assert.IsNull(foundClass);
        }
        [Test]
        public void Test_FindClassByMappedTableName_WithTwoClasses_TableNameLowerCase()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            DMClass dmClass = dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            dmClass.ClassNameBO = "FoundBO";
            const string mappedtablename = "MappedTableName";
            dmClass.MappedTableName = mappedtablename;
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, dmSolution.AllClasses.Count);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.IsTrue(dmSolution.AllClasses.Contains(dmClass));
            //---------------Execute Test ----------------------
            DMClass foundClass = dmSolution.FindClassByMappedTableName(mappedtablename.ToLower());
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundClass);
            Assert.AreSame(dmClass, foundClass);
        }
        [Test]
        public void Test_SetDefaultAssemblyAddsTheAssemblyToTheAssemblies()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = new DMSolution();
            dmSolution.SolutionName = TestUtilsShared.GetRandomString();
            dmSolution.SolutionDirectory = TestUtilsShared.GetRandomString();
            
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.DefaultAssembly);
            Assert.AreEqual(0, dmSolution.Assemblies.Count);
            //---------------Execute Test ----------------------
            dmSolution.DefaultAssembly = new DMAssembly("Some AssemblyName");
            //---------------Test Result -----------------------
            Assert.IsNotNull(dmSolution.DefaultAssembly);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.AreSame(dmSolution.DefaultAssembly, dmSolution.Assemblies[0]);
        }     
        [Test]
        public void Test_SetDefaultAssembly_AssemblyAlreadyExistsInAssembliesCollection()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = new DMSolution();
            DMAssembly assembly = new DMAssembly("Some AssemblyName");
            dmSolution.Assemblies.Add(assembly);
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.DefaultAssembly);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.AreSame(assembly, dmSolution.Assemblies[0]);
            //---------------Execute Test ----------------------
            dmSolution.DefaultAssembly = assembly;
            //---------------Test Result -----------------------
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.AreSame(assembly, dmSolution.Assemblies[0]);
            Assert.AreSame(assembly, dmSolution.DefaultAssembly);
        }    
        [Test]
        public void Test_SetDefaultAssemblyNull_ShouldNotAddToAssemblies()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = new DMSolution();
            DMAssembly assembly = new DMAssembly("Some AssemblyName");
            dmSolution.Assemblies.Add(assembly);
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.DefaultAssembly);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.AreSame(assembly, dmSolution.Assemblies[0]);
            //---------------Execute Test ----------------------
            dmSolution.DefaultAssembly = null;
            //---------------Test Result -----------------------
            Assert.IsNull(dmSolution.DefaultAssembly);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.AreSame(assembly, dmSolution.Assemblies[0]);
        }

        [Test]
        public void Test_Validate_NoClasses_ShouldReturnEmptyErrorList()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateUnsavedValidDMSolution();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dmSolution.AllClasses.Count);
            IList<IBOError> errors;
            Assert.IsFalse(dmSolution.Status.HasWarnings(out errors));
            //---------------Execute Test ----------------------
            IList<IBOError> allSolutionErrors = dmSolution.Validate();
            //---------------Test Result -----------------------
            Assert.AreEqual(0, allSolutionErrors.Count);
        }

        [Test]
        public void Test_Validate_WithOneClassWithWarnings_ShouldReturnNonEmptyErrorList()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateUnsavedValidDMSolution();
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass(dmSolution.DefaultAssembly);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmSolution.AllClasses.Count);
            IList<IBOError> errors;
            Assert.IsFalse(dmSolution.Status.HasWarnings(out errors));
            Assert.IsTrue(dmClass.Status.HasWarnings(out errors));
            //---------------Execute Test ----------------------
            IList<IBOError> allSolutionErrors = dmSolution.Validate();
            //---------------Test Result -----------------------
            Assert.AreEqual(2, allSolutionErrors.Count);
            AssertErrorsAreAssociatedWithDMClass(allSolutionErrors, dmClass);
        }
        [Test]
        public void Test_Validate_WithLookupList__ShouldReturnNonEmptyErrorList()
        {
            //---------------Set up test pack-------------------
            DMLookupListBusinessObject lookupList =
                TestUtilsDMBusinessObjectLookupList.CreateSavedDMBusinessObjectLookupList();
            DMClass dmClass = lookupList.DMClass;
            TestUtilsDMProperty.CreateUnsavedValidDMProperty(dmClass);
            TestUtilsDMProperty.CreateUnsavedValidDMProperty(dmClass);
            DMSortOrder order = new DMSortOrder();
            DMSortProperty dmSortProperty2 = order.DMSortProperties.CreateBusinessObject();
            dmSortProperty2.PropertyName = "SomeUnknownProp";
            lookupList.DMSortOrder = order;
            IDMSolution dmSolution = dmClass.Solution;

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmSolution.AllClasses.Count);
            IList<IBOError> errors;
            Assert.IsFalse(dmSolution.Status.HasWarnings(out errors));
            Assert.IsTrue(lookupList.Status.HasWarnings(out errors));
            Assert.IsTrue(dmClass.Status.HasWarnings(out errors));
            //---------------Execute Test ----------------------
            IList<IBOError> allSolutionErrors = dmSolution.Validate();
            //---------------Test Result -----------------------
            Assert.AreEqual(1, allSolutionErrors.Count);
            AssertErrorsAreAssociatedWithDMClass(allSolutionErrors, dmClass);
        }

        private static void AssertErrorsAreAssociatedWithDMClass(IEnumerable<IBOError> errors, DMClass dmClass)
        {
            foreach (IBOError error in errors)
            {
                Assert.AreSame(dmClass, error.BusinessObject, "Error '" + error.Message + "' should be associated with DMClass '" + dmClass +"'");
            }
        }

        private static void AssertErrorsAreAssociatedWithDMProperty(IEnumerable<IBOError> errors, DMProperty dmProperty)
        {
            foreach (IBOError error in errors)
            {
                Assert.AreSame(dmProperty, error.BusinessObject, "Error '" + error.Message + "' should be associated with DMProperty '" + dmProperty + "'");
            }
        }

        private static void AssertErrorsAreAssociatedWithDMObjectIdentity(IEnumerable<IBOError> errors, DMObjectIdentity dmObjectIdentity)
        {
            foreach (IBOError error in errors)
            {
                Assert.AreSame(dmObjectIdentity, error.BusinessObject, "Error '" + error.Message + "' should be associated with DMObjectIdentity '" + dmObjectIdentity + "'");
            }
        }

        private static void AssertErrorsAreAssociatedWithDMLookupListSimple(IEnumerable<IBOError> errors, DMLookupListSimple dmLookupListSimple)
        {
            foreach (IBOError error in errors)
            {
                Assert.AreSame(dmLookupListSimple, error.BusinessObject, "Error '" + error.Message + "' should be associated with DMLookupListSimple '" + dmLookupListSimple + "'");
            }
        }

        [Test]
        public void Test_Validate_WithOneClassWithNoWarnings_ShouldReturnEmptyErrorList()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateUnsavedValidDMSolution();
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass(dmSolution.DefaultAssembly);
            DMProperty property = TestUtilsShared.CreateUnsavedValidDMProperty(dmClass);
            dmClass.CreateObjectIdentity(property);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmSolution.AllClasses.Count);
            IList<IBOError> errors;
            Assert.IsFalse(dmSolution.Status.HasWarnings(out errors));
            Assert.IsFalse(dmClass.Status.HasWarnings(out errors));
            //---------------Execute Test ----------------------
            IList<IBOError> allSolutionErrors = dmSolution.Validate();
            //---------------Test Result -----------------------
            Assert.AreEqual(0, allSolutionErrors.Count);
        }

        [Test]
        public void Test_SetGeneratedFlagFalseThenTrue_ShouldSetTheStatusToDirty()
        {
            //--------------- Set up test pack ------------------
            DMSolution dmSolution = TestUtilsShared.CreateUnsavedValidDMSolution();
            dmSolution.Generated = true;
            dmSolution.Save();
            IBOProp prop = dmSolution.Props["Generated"];
            //--------------- Test Preconditions ----------------
            Assert.IsFalse(dmSolution.Status.IsNew);
            Assert.IsFalse(dmSolution.Status.IsDirty);
            Assert.IsTrue(dmSolution.Generated.GetValueOrDefault());
            Assert.IsFalse(prop.IsDirty);
            //--------------- Execute Test ----------------------
            dmSolution.Generated = false;
            prop.BackupPropValue();
            dmSolution.Generated = true;
            //--------------- Test Result -----------------------
            Assert.IsFalse(dmSolution.Status.IsNew);
            Assert.IsTrue(dmSolution.Status.IsDirty);
            Assert.IsTrue(dmSolution.Generated.Value);
            Assert.IsTrue(prop.IsDirty);
        }


        [Test]
        public void Test_Validate_WithSuperclass_withNonStringPropDiscriminator_ShouldReturnNonEmptyErrorList()
        {
            //---------------Set up test pack-------------------
            DMProperty dmProperty = TestUtilsShared.CreateSavedDMProperty();
            TestUtilsDMProperty.SetDMPropIntType(dmProperty);
            dmProperty.Save();
            DMInheritanceRelationship dmInheritanceRelationship = new DMInheritanceRelationship();
            DMAssembly assembly = dmProperty.Class.Assembly;
            DMSolution solution = assembly.Solution;
            DMClass subClass = TestUtilsShared.CreateSavedDMClass(assembly);
            dmInheritanceRelationship.SubClass = subClass;
            dmInheritanceRelationship.SuperClass = (DMClass) dmProperty.Class;
            dmInheritanceRelationship.Discriminator = dmProperty.PropertyName;
            dmProperty.Compulsory = true;
            dmProperty.ReadWriteRule = PropReadWriteRule.WriteOnce;
            subClass.Save();
            dmInheritanceRelationship.Save();
            //---------------Assert Precondition----------------
            IList<IBOError> errors;
            Assert.IsFalse(solution.Status.HasWarnings(out errors));
            Assert.IsTrue(dmInheritanceRelationship.Status.HasWarnings(out errors));
            //---------------Execute Test ----------------------
            IList<IBOError> allSolutionErrors = solution.Validate();
            //---------------Test Result -----------------------
            Assert.AreEqual(2, allSolutionErrors.Count);
            AssertInErrorList(allSolutionErrors, dmInheritanceRelationship);
        }

        [Test]
        public void Test_Validate_HasClassWithSpecialCharsInName_ShouldReturnNonEmptyErrorList()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateUnsavedValidDMSolution();
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass(dmSolution.DefaultAssembly);
            TestUtilsShared.CreateUnsavedValidObjectIdentityInfo(dmClass);
            dmClass.ClassNameBO = dmClass.ClassNameBO + "$^";
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmSolution.AllClasses.Count);
            IList<IBOError> errors;
            Assert.IsFalse(dmSolution.Status.HasWarnings(out errors));
            Assert.IsTrue(dmClass.Status.HasWarnings(out errors));
            //---------------Execute Test ----------------------
            IList<IBOError> allSolutionErrors = dmSolution.Validate();
            //---------------Test Result -----------------------
            Assert.AreNotEqual(0, allSolutionErrors.Count);
            AssertErrorsAreAssociatedWithDMClass(allSolutionErrors, dmClass);
        }

        [Test]
        public void Test_Validate_HasPropertyWithSpecialCharsInName_ShouldReturnNonEmptyErrorList()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateUnsavedValidDMSolution();
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass(dmSolution.DefaultAssembly);
            TestUtilsShared.CreateUnsavedValidObjectIdentityInfo(dmClass);
            dmClass.ClassNameBO = dmClass.ClassNameBO;
            DMProperty dmProperty = dmClass.CreateDMProp();
            dmProperty.PropertyName = "t$7y45";
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmSolution.AllClasses.Count);
            IList<IBOError> errors;
            Assert.IsFalse(dmSolution.Status.HasWarnings(out errors));
            Assert.IsTrue(dmProperty.Status.HasWarnings(out errors));
            //---------------Execute Test ----------------------
            IList<IBOError> allSolutionErrors = dmSolution.Validate();
            //---------------Test Result -----------------------
            Assert.AreEqual(1, allSolutionErrors.Count);
            AssertErrorsAreAssociatedWithDMProperty(allSolutionErrors, dmProperty);
        }

        [Test]
        public void Test_Validate_HasDMObjectIdentityWithNonCompulsoryProp_ShouldReturnNonEmptyErrorList()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateUnsavedValidDMSolution();
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass(dmSolution.DefaultAssembly);
            DMObjectIdentity dmObjectIdentity = TestUtilsShared.CreateUnsavedValidObjectIdentityInfo(dmClass);
            DMProperty property = dmObjectIdentity.Properties[0];
            property.Compulsory = false;
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmSolution.AllClasses.Count);
            IList<IBOError> errors;
            Assert.IsFalse(dmSolution.Status.HasWarnings(out errors));
            Assert.IsTrue(dmObjectIdentity.Status.HasWarnings(out errors));
            //---------------Execute Test ----------------------
            IList<IBOError> allSolutionErrors = dmSolution.Validate();
            //---------------Test Result -----------------------
            Assert.AreEqual(1, allSolutionErrors.Count);
            AssertErrorsAreAssociatedWithDMObjectIdentity(allSolutionErrors, dmObjectIdentity);
        }

        [Test]
        public void Test_Validate_HasDMLookupListSimplyWithNoItem_ShouldReturnNonEmptyErrorList()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateUnsavedValidDMSolution();
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass(dmSolution.DefaultAssembly);
            DMObjectIdentity dmObjectIdentity = TestUtilsShared.CreateUnsavedValidObjectIdentityInfo(dmClass);
            DMProperty property = dmObjectIdentity.Properties[0];
            DMLookupListSimple dmLookupListSimple = new DMLookupListSimple {DMProperty = property};
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmSolution.AllClasses.Count);
            IList<IBOError> errors;
            Assert.IsFalse(dmSolution.Status.HasWarnings(out errors));
            Assert.IsTrue(dmLookupListSimple.Status.HasWarnings(out errors));
            //---------------Execute Test ----------------------
            IList<IBOError> allSolutionErrors = dmSolution.Validate();
            //---------------Test Result -----------------------
            Assert.AreEqual(1, allSolutionErrors.Count);
            AssertErrorsAreAssociatedWithDMLookupListSimple(allSolutionErrors, dmLookupListSimple);
        }

        [Test]
        public void Test_Validate_HasDMAssemblyWithDuplicateClassNames_ShouldReturnNonEmptyErrorList()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateUnsavedValidDMSolution();
            DMAssembly dmAssembly = TestUtilsShared.CreateUnsavedValidProjectAssemblyInfo(dmSolution);
            string className = TestUtilsShared.GetRandomString();
            DMClass dmClass = dmAssembly.CreateClass(className);
            dmClass.CreateObjectIdentity(TestUtilsShared.CreateUnsavedValidDMProperty(dmClass));
            DMClass dmClass2 = dmAssembly.CreateClass(className);
            dmClass2.CreateObjectIdentity(TestUtilsShared.CreateUnsavedValidDMProperty(dmClass2));
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, dmSolution.AllClasses.Count);
            IList<IBOError> errors;
            Assert.IsFalse(dmSolution.Status.HasWarnings(out errors));
            //---------------Execute Test ----------------------
            IList<IBOError> allSolutionErrors = dmSolution.Validate();
            //---------------Test Result -----------------------
            Assert.AreEqual(1, allSolutionErrors.Count);
            //AssertErrorsAreAssociatedWithDMLookupListSimple(allSolutionErrors, dmLookupListSimple);
        }

        private static void AssertInErrorList(IEnumerable<IBOError> allSolutionErrors, DMInheritanceRelationship dmInheritanceRelationship)
        {
            bool found = false;
            foreach (IBOError error in allSolutionErrors)
            {
                if (error.BusinessObject == dmInheritanceRelationship)
                {
                    found = true;
                    break;
                }
            }
            Assert.IsTrue(found, "should be associated with DMInheritanceRelationship '" + dmInheritanceRelationship + "'");
        }
        [Test]
        public void Test_SetParentExceptionThrown()
        {
            //---------------Set up test pack-------------------
            IModelSolution solution = new DMSolution();

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            Exception exceptionThrown = null;
            try
            {
                solution.Parent = new DMSolution();
            }
            catch (Exception ex)
            {
                exceptionThrown = ex;
            }
            //---------------Test Result -----------------------
            Assert.IsNotNull(exceptionThrown);
            Assert.IsInstanceOf(typeof(HabaneroDeveloperException), exceptionThrown);
            StringAssert.Contains("A solution cannot have a parent", exceptionThrown.Message);
        }


        [Test]
        public void Test_GetParentIsNull()
        {
            //---------------Set up test pack-------------------


            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IModelSolution solution = new DMSolution();
            //---------------Test Result -----------------------
            Assert.IsNull(solution.Parent);
        }

        [Test]
        public void Test_GetAllModelClasses()
        {
            //---------------Set up test pack-------------------
            IModelSolution solution = new DMSolution();
            ((DMSolution)solution).Assemblies.Add(new DMAssembly(GetRandomString()));
            DMClass dmClass1 = new DMClass();
            DMClass dmClass2 = new DMClass();
            DMClass dmClass3 = new DMClass();

            //---------------Assert Precondition----------------
            Assert.AreEqual(0, solution.ModelClasses.Count);
            //---------------Execute Test ----------------------
            BusinessObjectCollection<DMClass> classes = ((DMSolution)solution).Assemblies[0].Classes;
            classes.Add(dmClass1);
            classes.Add(dmClass2);
            classes.Add(dmClass3);

            //---------------Test Result -----------------------
            Assert.AreEqual(3, classes.Count);
            Assert.AreEqual(3, solution.ModelClasses.Count);
            Assert.AreSame(dmClass1, solution.ModelClasses[0]);
            Assert.AreSame(dmClass2, solution.ModelClasses[1]);
            Assert.AreSame(dmClass3, solution.ModelClasses[2]);
        }

        [Test]
        public void Test_SetAssmeblies()
        {
            //---------------Set up test pack-------------------
            DMSolution solution = new DMSolution();
            DMAssembly assembly = new DMAssembly(GetRandomString());
            solution.Assemblies.Add(assembly);

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IList<IModelAssembly> assemblies = ((IModelSolution)solution).ModelAssemblies;
            //---------------Test Result -----------------------
            Assert.AreEqual(1, assemblies.Count);
            Assert.AreSame(assembly, assemblies[0]);
        }


        //Testing of project name properties will be generated by test generation

        [Test]
        public void Test_SetSolutionName_WhenHasDefaultAssembly_ShouldRename()
        {
            //---------------Set up test pack-------------------
            DMSolution solution = new DMSolution(GetRandomString());
            DMAssembly assembly = new DMAssembly(GetRandomString());
            solution.DefaultAssembly = assembly;
            //---------------Assert Precondition----------------
            Assert.IsNotNull(solution.DefaultAssembly);
            Assert.AreNotEqual(solution.SolutionName, assembly.AssemblyName.Substring(0, assembly.AssemblyName.Length -3));
            //---------------Execute Test ----------------------
            solution.SolutionName = GetRandomString();
            //---------------Test Result -----------------------
            Assert.IsTrue(assembly.AssemblyName.StartsWith(solution.SolutionName));
            Assert.AreEqual(solution.SolutionName + ".BO",  assembly.AssemblyName);
        }

        private string GetRandomString()
        {
            return RandomValueGen.GetRandomString();
        }
    }
}
